#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <omp.h>

#include "lib.h"

int main(int argc, char **argv){
	int 	nProcessadores = omp_get_num_procs(), cntProcessadores, 
		tamanhoArquivo, inicioParticao, fimParticao, 
		nPalindromos, nPrimos, primos[10000];
	FILE *fp;
	char *buffer, **particoes;

	/* abre o arquivo de texto */
	fp = fopen("data-t2/wikipedia.txt", "r");

	/* verifica se o arquivo foi aberto */
	if(fp == NULL){
		printf("ERRO: Nao foi possivel abrir o arquivo data-t2/wikipedia.txt!!!\n");
		exit(1);
	}

	/* calcula o tamanho do arquivo */
	fseek(fp, 0, SEEK_END);
	tamanhoArquivo = ftell(fp);

	/* retorna o ponteiro para o inicio do arquivo */
	fseek(fp, 0, SEEK_SET);

	/* aloca o buffer para carregar o arquivo na memoria */
	buffer = (char *)malloc(sizeof(char) * tamanhoArquivo);

	/* carrega o arquivo na memoria */
	fread(buffer, sizeof(char), tamanhoArquivo, fp);

	/* fecha o arquivo */
	fclose(fp);

	/* aloca o vetor de particoes */
	particoes = (char **)malloc(sizeof(char *) * nProcessadores);

	/* divide o texto em particoes e envia para os processos */
	inicioParticao = fimParticao = 0;
	for(cntProcessadores = 0; cntProcessadores < nProcessadores - 1; ++cntProcessadores){
		/* calcula o fim da particao */
		fimParticao = ((float)tamanhoArquivo / nProcessadores) * (cntProcessadores + 1);

		/* ajusta o fim da particao para nao dividir uma palavra */
		while(buffer[fimParticao] != ' '){
			++fimParticao;
		}

		buffer[fimParticao] = '\0'; /* marca o fim da particao */

		/* aloca a nova particao e copia o texto para ela */
		particoes[cntProcessadores] = (char *)malloc(sizeof(char) * (strlen(&buffer[inicioParticao]) + 1));
		strcpy(particoes[cntProcessadores], &buffer[inicioParticao]);

		buffer[fimParticao] = ' ';

		/* calcula o inicio da proxima particao */
		inicioParticao = fimParticao;
	}

	particoes[cntProcessadores] = (char *)malloc(sizeof(char) * (strlen(&buffer[inicioParticao]) + 1));
	strcpy(particoes[cntProcessadores], &buffer[inicioParticao]);

	/* encontra os 10000 primeiros primos */
	crivoEratostenes(primos, 10000);

	/* cria uma regiao paralela */
	#pragma omp parallel shared(particoes, primos)
	{
		/* faz cada thread processar uma particao do texto (em paralelo) */
		#pragma omp for schedule(static) private(cntProcessadores, nPrimos, nPalindromos)
		for(cntProcessadores = 0; cntProcessadores < nProcessadores; ++cntProcessadores){
			/* processa a particao e retorna o numero de palindromos e de primos */
			processaParticao(particoes[cntProcessadores], primos, &nPalindromos, &nPrimos);
			
			fprintf(stderr, 
				"Particao %d pela thread %d tem %d palindromos e %d primos.\n", 
				cntProcessadores,  
				omp_get_thread_num(),
				nPalindromos,
				nPrimos);
		}
	}

	/* desaloca as particoes */
	for(cntProcessadores = 0; cntProcessadores < nProcessadores; ++cntProcessadores){
		free(particoes[cntProcessadores]);
	}
	free(particoes);

	/* desaloca o buffer */
	free(buffer);

	return 0;
}
